﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SqlImEx.Sql;
using System.IO;
using SqlImEx.Xml;
using System.Diagnostics;

namespace SqlImEx
{
    class Program
    {
        StreamWriter _dwriter=null;
        Args _args;

        static void Main(string[] args)
        {
            var p = new Program(new Args(args));
            p.Start();
        }

        public Program(Args args)
        {
            _args = args;
        }

        void Start()
        {
            Configuration config = null;
            ISqlContext context;
            string svr = _args["s"];
            string db = _args["d"];
            string usr = _args["u"];
            string pw = _args["p"];
            string exportPath = _args["e"];
            string importPath = _args["i"];
            string log = _args["log"];
            string conf = _args["conf"];
            bool compactEdition = _args["ce"] != null;
            bool incrementalExport = _args["inc"]!=null;
            bool help = _args["?"] != null;
            bool debug = _args["dbg"] != null;
            if (debug)
                Debugger.Launch();
            if (help)
            {
                Help();
                return;
            }
            //string 
            if (log != null)
                _dwriter = new StreamWriter(CombinePath(log));
            if (conf != null)
                config = Serializer.DeSerialize<Configuration>(File.ReadAllText(CombinePath(conf)));
            if (compactEdition)
                context = new SqlCeContext(BuildSimpleCompactConnString(svr, pw));           
            else
                context = new SqlContext(BuildSimpleSqlConnectionString(svr, db, usr, pw));
            if (!string.IsNullOrEmpty(exportPath))
            {
                if (incrementalExport)
                    exportPath = CreateIncremental(CombinePath(exportPath));
                var exporter = new Exporter(context, exportPath);
                exporter.DebugWrite = DebugWrite;
                exporter.Configuration = config;
                exporter.Export();
            }
            else if (!string.IsNullOrEmpty(importPath))
            {
                if (incrementalExport)
                    importPath = GetIncremental(CombinePath(importPath));
                var importer = new Importer(context, importPath);
                importer.DebugWrite = DebugWrite;
                importer.Configuration = config;
                importer.Import();
            }
            else
                Help();
            if (_dwriter != null)
                _dwriter.Dispose();
            //Console.ReadKey();
        }

        void DebugWrite(string msg)
        {
            Console.Write(msg);
            if (_dwriter != null)
            {
                _dwriter.Write(msg);
                _dwriter.Flush();
            }
        }

        void Help()
        {
            Console.WriteLine("Sqlimex help");
            Console.WriteLine("/s:\tSQL Server");
            Console.WriteLine("/d:\tDatabase");
            Console.WriteLine("[/u:]\tLogin");
            Console.WriteLine("[/p:]\tPassword");
            Console.WriteLine("[/e:]\tExport path");
            Console.WriteLine("[/i:]\tImport path");
            Console.WriteLine("[/debug]:\tDebug output file");
            Console.WriteLine("[/conf:]\tXml configuration file");
            Console.WriteLine("[/ce]\tCompact edition");
            Console.WriteLine("[/inc]\tIncremental Export/Import");
            Console.WriteLine("[/dbg]\tAttach debugger");
        }

        static string CreateIncremental(string path)
        {
            string ext = Path.GetExtension(path);
            string fpath = Path.GetDirectoryName(path);
            string file = Path.GetFileNameWithoutExtension(path);
            file = file + "-" + DateTime.Now.ToString("ddMMyy-HHmmss");
            return Path.Combine(fpath, file+ext);
        }

        static string GetIncremental(string path)
        {
            string ext = Path.GetExtension(path);
            string fpath = Path.GetDirectoryName(path);
            string file = Path.GetFileNameWithoutExtension(path);
            var filez = Directory.GetFiles(fpath, "*" + ext);
            var fileinfoz = filez.Select(x => new FileInfo(x)).Where(x => x.Name.StartsWith(file)).OrderByDescending(x => x.CreationTime).FirstOrDefault();
            if (fileinfoz == null)
                throw new Exception("Incremental File does not exist");
            return fileinfoz.FullName; 
        }

        static string BuildSimpleSqlConnectionString(string svr, string db, string usr, string pw)
        {
            var unpw = @"Password={3};Persist Security Info=True;User ID={2};Initial Catalog={1};Data Source={0}";
            var trco = @"Integrated Security=SSPI;Persist Security Info=False;Initial Catalog={1};Data Source={0}";
            if (string.IsNullOrEmpty(usr))
                return string.Format(trco, svr, db);
            else
                return string.Format(unpw, svr, db, usr, pw);
        }

        static string BuildSimpleCompactConnString(string datasource, string pw)
        {
            var encr = @"Data Source={0};Encrypt Database=True;Password={1};File Mode=shared read;Persist Security Info=False;";
            var noen = @"Data Source={0};Persist Security Info=False;";
            if (!string.IsNullOrEmpty(pw))
                return string.Format(encr, datasource, pw);
            return string.Format(noen, datasource);
        }

        public static string CombinePath( string path)
        {
            if (Path.IsPathRooted(path))
                return path;
            else
                return Path.Combine(Directory.GetCurrentDirectory(), path);
        }
    }
}
